package com.qp.basics.common.config;

import com.alibaba.druid.filter.FilterEventAdapter;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.proxy.jdbc.DataSourceProxy;
import com.alibaba.druid.proxy.jdbc.StatementProxy;
import com.qp.basics.common.config.redis.StringRedisSerializer;
import com.qp.basics.common.datasource.DynamicDataSource;
import com.qp.basics.common.datasource.enums.DataSourceType;
import com.qp.basics.common.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;


@Component
@Slf4j
public class InitDataService {
    @Autowired
    private JdbcTemplate jdbcTemplateBase;
    @Autowired
    DynamicDataSource dynamicDataSource;
    @Autowired
    RedisTemplate redisTemplate;
    @Autowired
    StringRedisTemplate stringRedisTemplate;
    @Value("${readonly.off:true}")
    private boolean readOnlyOff;

    @PostConstruct
    public void init() {
        initDB();
        initRedis();
    }

    public void initDB(Map<Object, Object> targetDataSources, Map<String, Object> m) {
        String driver = (String) m.get("driver");
        if (StringUtils.isEmpty(driver)) {
            driver = "com.mysql.cj.jdbc.Driver";
        }
        String host = (String) m.get("dbhost");
        String user = (String) m.get("dbuser");
        String dbname = (String) m.get("dbname");
        String password = (String) m.get("dbpwd");
        String domain = (String) m.get("domain");

        DruidDataSource master = (DruidDataSource) targetDataSources.get(DataSourceType.MASTER.name());
        DruidDataSource newDataSource = new DruidDataSource();
        BeanUtils.copyProperties(master, newDataSource);

        newDataSource.setDriverClassName(driver);

        String url = (String) m.get("url");
        if (StringUtils.isEmpty(url)) {
            url = "jdbc:mysql://" + host + "/" + dbname + "?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=GMT%2B8";
        }
        newDataSource.setUrl(url);
        newDataSource.setUsername(user);
        newDataSource.setPassword(password);

        targetDataSources.put(domain, newDataSource);
        dynamicDataSource.putDbname(domain, dbname);
        List pfs = new ArrayList();
        pfs.add(new TestFilter());
        newDataSource.setProxyFilters(pfs);

        //从库
        if (!readOnlyOff) {
            String host_r = (String) m.get("dbhost_r");
            String user_r = (String) m.get("dbuser_r");
            String dbname_r = (String) m.get("dbname_r");
            String password_r = (String) m.get("dbpwd_r");
            DruidDataSource rDataSource = new DruidDataSource();
            BeanUtils.copyProperties(master, rDataSource);

            rDataSource.setDriverClassName(driver);

            String url_r = (String) m.get("url_r");
            if (StringUtils.isEmpty(url_r)) {
                url_r = "jdbc:mysql://" + host_r + "/" + dbname_r + "?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=GMT%2B8";
            }
            rDataSource.setUrl(url_r);
            rDataSource.setUsername(user_r);
            rDataSource.setPassword(password_r);
            targetDataSources.put(domain + "_r", rDataSource);
            dynamicDataSource.putDbname(domain + "_r", dbname_r);
        }
    }

    public void initDB() {
        Map<Object, Object> targetDataSources = dynamicDataSource.getTargetDataSources();
        List<Map<String, Object>> apps = jdbcTemplateBase.queryForList("select * from sys_cust_app_config where (status is null or status!='停用')");
        for (Map<String, Object> m : apps) {
            initDB(targetDataSources, m);
        }

        dynamicDataSource.setTargetDataSources(targetDataSources);
        dynamicDataSource.afterPropertiesSet();
    }

    public void refreshDB(String domain) {
        List<Map<String, Object>> apps = jdbcTemplateBase.queryForList("select * from sys_cust_app_config where domain='" + domain + "' and (status is null or status!='停用')");
        if (apps.size() == 0) {
            log.error("domain: {} not founded or stopped in custAppConfig.", domain);
            return;
        }
        Map<Object, Object> targetDataSources = dynamicDataSource.getTargetDataSources();
        this.initDB(targetDataSources, apps.get(0));
        dynamicDataSource.afterPropertiesSet();

    }

    public void initRedis() {
        StringRedisSerializer r = new StringRedisSerializer();
        redisTemplate.setKeySerializer(r);
        redisTemplate.setHashKeySerializer(r);
        stringRedisTemplate.setKeySerializer(r);
    }
}
class TestFilter extends FilterEventAdapter {
    private static long timeMessage;

    @Override
    public void init(DataSourceProxy dataSource) {
        super.init(dataSource);
    }

    @Override
    protected void statementExecuteBefore(StatementProxy statement, String sql) {
        timeMessage = System.currentTimeMillis();
        if (sql.toLowerCase().contains("select") && !sql.toLowerCase().contains("where")) {
            throw new RuntimeException("没有条件的查询");
        }
        super.statementExecuteBefore(statement, sql);
    }

    @Override
    protected void statementExecuteAfter(StatementProxy statement, String sql, boolean result) {
        super.statementExecuteAfter(statement, sql, result);
        if (System.currentTimeMillis() - timeMessage > 2) {
            //xxxxx
        }
    }
}
